#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include "mongoose.h"
#include "cJSON.h"

#include <pthread.h>

// -----------------------------------------------------使用cmake编译测试～！！

// server

// int main(void) {
//     struct mg_mgr mgr;  // 初始化事件管理器
//     mg_mgr_init(&mgr);

//     // 在 8080 端口启动 HTTP 监听器，并指定事件处理函数 fn
//     mg_http_listen(&mgr, "http://0.0.0.0:8080", fn, NULL);

//     // 无限事件循环
//     for (;;) {
//         mg_mgr_poll(&mgr, 1000); // 每秒轮询一次
//     }

//     mg_mgr_free(&mgr); // 清理资源 (理论上不会执行到这里)
//     return 0;
// }

char auth_token[100];


char *api_request(struct mg_http_message *hm)
{

    // struct mg_str *body = &hm->body;
    // char *payload = NULL;
    

    // cJSON *request = cJSON_Parse(body->buf);
    // if (request == NULL)
    // {
    //     const char *error_ptr = cJSON_GetErrorPtr();
    //     if (error_ptr != NULL)
    //     {
    //         log_err("webapi_request", "Error before: %s\n", error_ptr);
    //     }
    //     return NULL;
    // }

    char *payload = strdup("hello world");
    return payload;
}

typedef struct
{
    const char *type;
    const char *url;
    char *(*fmethod)(struct mg_http_message *hm); // 参数更新为 mg_http_message
    int need_auth;
} mg_route_t;

static mg_route_t mg_route[] = {

    {"GET", "/request", api_request, false},

};


// ...existing code...

// 文件上传处理函数，兼容 Mongoose 7.14
void webapi_upload_dtu(struct mg_connection *c, struct mg_http_message *hm) {
    // 遍历所有 header，查找 Content-Type
    int is_multipart = 0;
    for (size_t i = 0; i < MG_MAX_HTTP_HEADERS && hm->headers[i].name.len > 0; i++) {
        if (hm->headers[i].name.len == 12 &&
            strncasecmp(hm->headers[i].name.buf, "Content-Type", 12) == 0) {
            // 判断是否 multipart/form-data
            if (hm->headers[i].value.len >= 19 &&
                strncasecmp(hm->headers[i].value.buf, "multipart/form-data", 19) == 0) {
                is_multipart = 1;
                break;
            }
        }
    }
    if (!is_multipart) {
        mg_http_reply(c, 400, "Content-Type: text/plain\r\n", "Bad Request: Not multipart/form-data\n");
        return;
    }


    // 2. 解析 multipart/form-data
    struct mg_http_part part;
    size_t ofs = 0;
    FILE *fp = fopen("./dtu.json", "wb");
    if (!fp) {
        mg_http_reply(c, 500, "Content-Type: text/plain\r\n", "Failed to open file\n");
        return;
    }

    int found = 0;
    while ((ofs = mg_http_next_multipart(hm->body, ofs, &part)) > 0) {
        // 只保存第一个文件字段（可根据 part.name 判断字段名）
        fwrite(part.body.buf, 1, part.body.len, fp);
        found = 1;
        break;
    }
    fclose(fp);

    if (found) {
        mg_http_reply(c, 200, "Content-Type: text/plain\r\n", "Upload OK\n");
    } else {
        mg_http_reply(c, 400, "Content-Type: text/plain\r\n", "No file part found\n");
    }
}

// ...existing code...


typedef struct
{
    const char *url;
    void (*fupload)(struct mg_connection *c, struct mg_http_message *hm); // 参数更新
} mg_upload_t;

static mg_upload_t mg_upload[] = {
    // 文件交互接口

    {"/dtu", webapi_upload_dtu},

};

// 静态文件服务配置选项 (变量名和结构体类型可能已更改)
static struct mg_http_serve_opts s_http_server_opts = {
    .root_dir = "./webserver", // 例如，设置web根目录
    .ssi_pattern = NULL,
    // ... 其他选项根据需要配置
};

static int has_prefix(const struct mg_str *uri, const struct mg_str *prefix)
{
    return uri->len >= prefix->len && memcmp(uri->buf, prefix->buf, prefix->len) == 0;
}

static int is_equal(const struct mg_str *s1, const struct mg_str *s2)
{
    return s1->len == s2->len && memcmp(s1->buf, s2->buf, s2->len) == 0;
}

// WebSocket 连接判断 (方法可能已变，建议查阅新版本文档)
static int is_websocket(const struct mg_connection *c)
{
    return c->is_websocket; // 这是一个可能的方式，请根据7.14文档确认
}

static void ev_handler(struct mg_connection *nc, int ev, void *ev_data)
{
    int i = 0;
    char uri[200] = {0};
    struct mg_http_message *hm = (struct mg_http_message *)ev_data;

    switch (ev)
    {
    case MG_EV_HTTP_MSG:
    {

        // 打印 method, uri
        printf("method: %.*s\n", (int)hm->method.len, hm->method.buf);
        printf("uri: %.*s\n", (int)hm->uri.len, hm->uri.buf);
        snprintf(uri, sizeof(uri), "%.*s", (int)hm->uri.len, hm->uri.buf); // 更安全的拷贝方式

        struct mg_str method_type = mg_str(mg_route[i].type);

        // 首先检查是否是上传接口列表中定义的接口
        for (i = 0; i < sizeof(mg_upload) / sizeof(mg_upload_t); i++) {
            // if (mg_http_match_uri(hm, mg_upload[i].url)) 
            
            // if (is_equal(&hm->method, &method_type))
            {
                if (strcmp(uri, mg_upload[i].url) == 0)
                {
                    // 如果匹配，则调用对应的处理函数
                    mg_upload[i].fupload(nc, hm);
                    return; // 处理完毕，直接返回，避免被其他逻辑处理
                }
            }
        }


        for (i = 0; i < sizeof(mg_route) / sizeof(mg_route_t); i++)
        {
            if (is_equal(&hm->method, &method_type))
            {
                if (strcmp(uri, mg_route[i].url) == 0)
                {
                    if (mg_route[i].fmethod != NULL)
                    {
                        char *payload = mg_route[i].fmethod(hm);
                        if (payload != NULL)
                        {

                            mg_printf(nc,
                                      "HTTP/1.1 200 OK\r\n"
                                      "Content-Type: text/plain\r\n"
                                      "Content-Length: %d\r\n\r\n%s",
                                      (int)strlen(payload), payload);
                            free(payload);
                        }
                        else
                        {
                            mg_printf(nc, "%s",
                                      "HTTP/1.0 501 Not Implemented\r\n"
                                      "Content-Length: 0\r\n\r\n");
                        }
                    }
                    else
                    {
                        mg_printf(nc, "%s",
                                  "HTTP/1.0 404 Not found\r\n"
                                  "Content-Length: 0\r\n\r\n");
                    }

                    return;
                }
            }
        }

        printf("not support-----------------------------\n");

        // 如果代码能执行到这里，说明请求的路由不支持
        mg_printf(nc, "%s",
                  "HTTP/1.1 404 Not Found\r\n"
                  "Content-Length: 0\r\n\r\n");

        break;
    }
    case MG_EV_WS_OPEN:
    {
        printf("joined!\n");
        break;
    }
    case MG_EV_WS_MSG:
    {
        struct mg_ws_message *wm = (struct mg_ws_message *)ev_data; // 数据结构可能不同
        char buf[500];
        snprintf(buf, sizeof(buf), "%.*s", (int)wm->data.len, wm->data.buf);
        printf("WebSocket message: %s\n", buf);

        break;
    }
    case MG_EV_CLOSE:
    {
        /* Disconnect. Tell everybody. */
        if (is_websocket(nc))
        {
            // websocket_stop();
            printf("leave!\n");
        }
        break;
    }
    default:
        break;
    }
}

int main(void)
{
    struct mg_mgr mgr;        // 事件管理器
    struct mg_connection *nc; // 网络连接对象
                              //   int i;

    // 初始化事件管理器 (Mongoose 7.x 版本只需要一个参数)
    mg_mgr_init(&mgr);

    // 创建HTTP监听器 - 使用新版本的mg_http_listen函数
    // FIXME: 127.0.0.1??
    nc = mg_http_listen(&mgr, "http://192.168.182.131:8080", ev_handler, NULL);
    if (nc == NULL)
    {
        printf("bind webport:%s error!", "8080");
        return -1;
    }

    //   // 注册自定义HTTP端点（上传接口）
    //   for (i = 0; i < sizeof(mg_upload) / sizeof(mg_upload_t); i++)
    //   {
    //     // Mongoose 7.x 使用新的端点注册API
    //     mg_http_add_endpoint(nc, mg_upload[i].url, ev_handler, NULL);
    //   }

    // 配置HTTP服务器选项
    static struct mg_http_serve_opts s_http_server_opts = {0};
    //   s_http_server_opts.root_dir = "./webserver";      // 设置Web根目录
    //   s_http_server_opts.enable_directory_listing = "yes";     // 启用目录列表

    printf("Starting RESTful server on port %s\n", "8080");

    // 主事件循环
    while (1)
    {
        mg_mgr_poll(&mgr, 1000); // 处理事件，超时1秒
    }

    // 清理资源（理论上不会执行到这里）
    mg_mgr_free(&mgr);
    return 0;
}

/*

// client

#define API_HOST "101.37.151.118:20001"

static const char *s_url = "http://101.37.151.118:20001/exchange/device/register?productKey=MTAxNDM0MTg4NjYyOTk2MTcyOA&secretKey=1e13aa925960e001&sn=ABCD0123456789";

static const uint64_t s_timeout_ms = 1500;

static void ev_handler(struct mg_connection *conn, int ev, void *ev_data)
{

    printf("ev_handler_reg called with event: %d\n", ev);

    if (ev == MG_EV_OPEN)
    {
        // Connection created. Store connect expiration time in c->data
        *(uint64_t *)conn->data = mg_millis() + s_timeout_ms;
    }
    else if (ev == MG_EV_POLL)
    {
        if (mg_millis() > *(uint64_t *)conn->data &&
            (conn->is_connecting || conn->is_resolving))
        {
            mg_error(conn, "Connect timeout");
        }
    }
    else if (ev == MG_EV_CONNECT)
    {
        // Connected to server. Extract host name from URL
        printf("Connected to server!!\n");

    }
    else if (ev == MG_EV_HTTP_MSG)
    {
        struct mg_http_message *hm = (struct mg_http_message *)ev_data;
        // 处理HTTP响应
        // std::cout << "Response body: \n" << hm->body.buf << std::endl;

        // 打印HTTP响应状态码
        printf("HTTP Status: %.*s\n", hm->uri.len, hm->uri.buf); // 旧代码可删除
        printf("HTTP Response Body: %.*s\n", hm->body.len, hm->body.buf); // 旧代码可删除

        bool *done = (bool *)conn->fn_data;
        *done = true;
    }
}

int main(void)
{

    char content[500] = {0};
    sprintf(content, "GET /exchange/device/register?productKey=MTAxNDM0MTg4NjYyOTk2MTcyOA&secretKey=1e13aa925960e001&sn=ABCD0123456789 HTTP/1.1\r\nHost: %s\r\n\r\n", API_HOST);

    struct mg_mgr mgr;
    mg_mgr_init(&mgr);

    while (1)
    {
        bool done = false;
        struct mg_connection *c = mg_http_connect(&mgr, API_HOST, ev_handler, &done);
        if (c == NULL)
        {
            printf("Failed to connect\n");
        }
        else
        {
            mg_send(c, content,strlen(content));

            // 最多等待5秒
            int wait_ms = 0;
            while (!done && wait_ms < 5000)
            {
                mg_mgr_poll(&mgr, 100);
                wait_ms += 100;
            }
            if (!done)
            {
                printf("Request timeout after 5 seconds\n");
            }
        }
        // 3秒周期
        sleep(3);
    }

    mg_mgr_free(&mgr);

    return 0;
}

*/

/*

//  -- 文件下载！！！！！！！！！！！！
// curl -O "http://192.168.182.131:8080/download?filename=dtu.json"

#include "mongoose.h" // Mongoose 核心头文件

static void handle_download_request(struct mg_connection *c, struct mg_http_message *hm) {
    char filename[256] = {0};
    char full_path[512] = {0};
    struct mg_http_part part;
    const char *default_root = "./"; // 设置一个安全的默认文件根目录

    // 1. 从查询字符串中获取文件名
    mg_http_get_var(&hm->query, "filename", filename, sizeof(filename));

    // 2. 构造完整的文件路径（注意：务必进行安全校验，防止路径遍历攻击）
    if (filename[0] == '\0') {
        mg_http_reply(c, 400, "Content-Type: text/plain\r\n", "Filename parameter missing\n");
        return;
    }

    // 简单的安全校验：防止路径遍历攻击 (例如 filename=../../../etc/passwd)
    if (strstr(filename, "..") != NULL) {
        mg_http_reply(c, 403, "Content-Type: text/plain\r\n", "Forbidden: Invalid filename\n");
        return;
    }

    snprintf(full_path, sizeof(full_path), "%s/%s", default_root, filename);

    // 3. 检查文件是否存在并可读
    FILE *file = fopen(full_path, "rb");
    if (file == NULL) {
        mg_http_reply(c, 404, "Content-Type: text/plain\r\n", "File not found\n");
        return;
    }

    // 4. 获取文件大小
    fseek(file, 0, SEEK_END);
    long file_size = ftell(file);
    fseek(file, 0, SEEK_SET);

    // 5. 设置 HTTP 响应头，指示浏览器下载文件
    mg_printf(c, // mg_printf 用于向连接输出数据
              "HTTP/1.1 200 OK\r\n"
              "Content-Type: application/octet-stream\r\n" // 通用二进制类型，强制下载
              "Content-Length: %ld\r\n"
              "Content-Disposition: attachment; filename=\"%s\"\r\n" // 建议浏览器保存的文件名
              "Connection: close\r\n\r\n", // 发送完文件后关闭连接
              file_size, filename);

    // 6. 发送文件内容
    char buffer[1024 * 8]; // 8KB 缓冲区
    size_t bytes_read;
    while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) {
        mg_send(c, buffer, bytes_read); // 发送数据块
    }

    fclose(file);
}

static void event_handler(struct mg_connection *c, int ev, void *ev_data) {
    if (ev == MG_EV_HTTP_MSG) {
        struct mg_http_message *hm = (struct mg_http_message *) ev_data;

        // 检查请求方法和路径，例如 GET /download?filename=myfile.zip
        // if (mg_http_match_uri(hm, "/download"))
        {
            printf("-----------------\n");
            handle_download_request(c, hm);
        }
        // else {
        //     // 可以返回其他响应，例如 404
        //     mg_http_reply(c, 404, "Content-Type: text/plain\r\n", "Not Found\n");
        // }
    }
}

// 全局管理器
static struct mg_mgr s_mgr;

int main(void) {
    mg_mgr_init(&s_mgr); // 初始化事件管理器

    // 在 8080 端口启动 HTTP 监听器，指定事件处理函数为 event_handler
    if (mg_http_listen(&s_mgr, "http://192.168.182.131:8080", event_handler, NULL) == NULL) {
        fprintf(stderr, "Failed to create listener on port 8080\n");
        return EXIT_FAILURE;
    }

    printf("HTTP server started on http://192.168.182.131:8080\n");

    // 主事件循环
    for (;;) {
        mg_mgr_poll(&s_mgr, 1000); // 每秒轮询一次处理网络事件
    }

    mg_mgr_free(&s_mgr); // 清理资源 (理论上不会执行到这里)
    return 0;
}

*/